/*
 * DesktopPane.java  0.4.0 / Oct 26, 2010
 *
 * Copyright (c) 2010 - 2011, cute4j.com and contributors.
 *
 * This software is licensed under the LGPL version 2.1 license.
 * A copy of this license is included in the file LICENSE-LGPL.txt.
 */
package com.cute4j.swing;

import com.cute4j.swing.layouts.LayoutManager;

/**
 * DesktopPane Component.
 *
 * @cute4j.native
 *    generate="header"
 *
 * @author Slobodan Vrkacevic
 * @version 0.4.0
 */
public class DesktopPane extends Container {

// Private Fields. -------------------------------------------------------------

  private Component selectedComponent;

// Static Initialization. ------------------------------------------------------

  static {
    _initialize();
  }

// Public Constructors. --------------------------------------------------------

  /**
   * Constructs new DesktopPane object.
   */
  public DesktopPane() {
    super(null);
  }

// Public Methods. -------------------------------------------------------------

  /**
   * Appends the specified component to the end of this container.
   *
   * @param component the component to be added
   *
   * @return the component argument
   */
  public InternalFrame add(InternalFrame component) {
    addImpl(component, null, -1);
    return component;
  }

  /**
   * Returns currently selected (active) component.
   *
   * @return currently selected (active) component
   */
  public Component getSelectedComponent() {
    return selectedComponent;
  }

  /**
   * Sets currently selected (active) component.
   *
   * @param component the component to be selected
   */
  public void setSelectedComponent(Component component) {
    if (selectedComponent != component) { // NOPMD
      if (getComponentIndex(component) == -1) {
        throw new IllegalArgumentException("Invalid component");
      }
      disposedCheck();
      selectedComponent = component;
      if (component == null) {
        _setCurrentComponent(_delegate, 0);
      } else {
        _setCurrentComponent(_delegate, component._delegate);
      }
    }
  }

  /**
   * Selects next component.
   */
  public void selectNextComponent() {
    if (componentCount > 0) {
      disposedCheck();
      _selectNextComponent(_delegate);
    }
  }

  /**
   * Selects previous component.
   */
  public void selectPreviousComponent() {
    if (componentCount > 0) {
      disposedCheck();
      _selectPreviousComponent(_delegate);
    }
  }

  /**
   * Closes the current component.
   */
  public void closeCurrentComponent() {
    if (componentCount > 0) {
      disposedCheck();
      _closeCurrentComponent(_delegate);
    }
  }

  /**
   * Closes all components.
   */
  public void closeAllComponents() {
    if (componentCount > 0) {
      disposedCheck();
      _closeAllComponents(_delegate);
    }
  }

  /**
   * Cascades the components.
   */
  public void cascadeComponents() {
    if (componentCount > 0) {
      disposedCheck();
      _cascadeComponents(_delegate);
    }
  }

  /**
   * Tiles the components.
   */
  public void tileComponents() {
    if (componentCount > 0) {
      disposedCheck();
      _tileComponents(_delegate);
    }
  }

// Overridden Methods. ---------------------------------------------------------

  /**
   * {@inheritDoc}
   */
  public Component add(Component component) {
    return add(component, null, -1);
  }

  /**
   * {@inheritDoc}
   */
  public Component add(Component component, int index) {
    return add(component, null, -1);
  }

  /**
   * {@inheritDoc}
   */
  public Component add(Component component, Object constraints) {
    return add(component, null, -1);
  }

  /**
   * {@inheritDoc}
   */
  public Component add(Component component, Object constraints, int index) {
    if (component == null) {
      throw new IllegalArgumentException("Adding null component");
    }
    InternalFrame internalFrame;
    if (constraints instanceof String) {
      internalFrame = new InternalFrame((String)constraints);
    } else {
      internalFrame = new InternalFrame(component.getName());
    }
    internalFrame.addImpl(component, null, index);
    addImpl(internalFrame, null, index);
    return internalFrame;
  }

  /**
   * {@inheritDoc}
   */
  public void setLayout(LayoutManager layoutManager) {
    // empty method
  }

  /**
   * {@inheritDoc}
   */
  public void invalidate() {
    if (valid) {
      valid = false;
      if (visible) {
        disposedCheck();
        _validate(_delegate);
      }
    }
  }

  /**
   * {@inheritDoc}
   */
  public void validate() {
    if (!valid) {
      disposedCheck();
      valid = true;
      final Component[] components = this.components;
      for (int i = componentCount; --i >= 0;) {
        components[i].validate();
      }
    }
  }

  /**
   * {@inheritDoc}
   */
  protected Component addImpl(Component component, Object constraints,
                                int index) {
    return super.addImpl(component, constraints, index);
  }

  void checkChild(Component child) {
    if (child == null) {
      throw new IllegalArgumentException("Adding null child");
    }
    if (child.isDisposed()) {
      throw new IllegalArgumentException("Adding disposed child");
    }
    if (child instanceof Container) {
      for (Container cont = this; cont != null; cont = cont.parent) {
        if (cont == child) { // NOPMD
          throw new IllegalArgumentException(
                                        "Adding container's parent to itself");
        }
      }
    }
  }

// Native Callback. ------------------------------------------------------------

  void _activeComponentChanged(Component component) {
    selectedComponent = component;
  }

// Package-Private Native Methods. ---------------------------------------------

  native long _create();

  native void _insertChild(long delegate, long childDelegate, int index);

  native void _removeChild(long delegate, long childDelegate);

  native void _setCurrentComponent(long delegate, long componentDelegate);

  native void _selectNextComponent(long delegate);

  native void _selectPreviousComponent(long delegate);

  native void _closeCurrentComponent(long delegate);

  native void _closeAllComponents(long delegate);

  native void _cascadeComponents(long delegate);

  native void _tileComponents(long delegate);

// Private Static Native Methods. ----------------------------------------------

  private static native void _initialize();

}
